package org.robotlegs.xxl.base 
{
	import flash.utils.Dictionary;
	import org.osflash.signals.ISignal;
	import org.osflash.signals.Signal;
	import org.robotlegs.base.ContextError;
	import org.robotlegs.core.IInjector;
	import org.robotlegs.core.IReflector;
	import org.robotlegs.xxl.core.INameSignal;
	import org.robotlegs.xxl.core.ISignalMap;
	
	/**
	 * 用来替换原来的事件总线,实现的一般,吐槽点较多,边用边改了
	 * @author XXL
	 */
	public class SignalMap implements ISignalMap 
	{
		protected static var SignalClassMap:Dictionary = new Dictionary();
		
		protected var listeners:Array;
		protected var reflector:IReflector;
		protected var injector:IInjector;
		protected var useSignalClassMap:Dictionary;
		
		public function SignalMap(injector:IInjector, reflector:IReflector) 
		{
			this.injector = injector;
			this.reflector = reflector;
			
			listeners = [];
			useSignalClassMap = SignalClassMap;
		}
		
		protected function getSignalClassInstance(signalClass:Class, name:String):ISignal
        {
			var className:String = reflector.getFQCN(signalClass);
            return ISignal(getSignalFromDictionary(className, name)) || createSignalClassInstance(signalClass, name);
        }
		
		protected function createSignalClassInstance(signalClass:Class, name:String):ISignal 
		{
			var className:String = reflector.getFQCN(signalClass);
			var injectorForSignalInstance:IInjector = injector;
			var signal:ISignal;
			if (injector.hasMapping(IInjector))
			{
				injectorForSignalInstance = injector.getInstance(IInjector);
			}
			signal = injectorForSignalInstance.instantiate(signalClass);
			if (signal)
			{
				injectorForSignalInstance.mapValue(signalClass, signal, name);
				var tmpDictionary:Dictionary = useSignalClassMap[className];
				tmpDictionary[name] = signal;
			}
			return signal;
		}
		
		protected function getSignalFromDictionary(signalClsName:String, name:String = ""):ISignal
		{
			var tmpDictionary:Dictionary = useSignalClassMap[signalClsName];
			if (tmpDictionary == null)
			{
				tmpDictionary = new Dictionary();
				useSignalClassMap[signalClsName] = tmpDictionary;
			}
			return tmpDictionary[name];
		}
		
		/* INTERFACE org.robotlegs.xxl.core.ISignalMap */
		
		public function registerSignal(signalClass:Class, name:String = ""):ISignal 
		{
			var tmp:ISignal = getSignalClassInstance(signalClass, name);
			if (tmp == null)
			{
				throw new ContextError(ContextError.E_SIGNAL_NOIMPL + "-" + signalClass);
			}
			return tmp;
		}
		
		public function removeSignal(signalClass:Class, name:String = "", removeListeners:Boolean = true):void 
		{
			var className:String = reflector.getFQCN(signalClass);
			var tmpDictionary:Dictionary = useSignalClassMap[className];
			if (tmpDictionary)
			{
				var tmp:ISignal = tmpDictionary[name];
				if (tmp && removeListeners)
				{
					tmp.removeAll();
				}
				delete tmpDictionary[name];
			}
		}
		
		public function mapSignal(signal:ISignal, callback:Function, once:Boolean = false):void 
		{
			if (callback == null)
			{
				return;
			}
			if (signal)
			{
				if (once)
				{
					signal.addOnce(callback);
				}
				else
				{
					signal.add(callback);
				}
				var config:SignalMapConfig = new SignalMapConfig()
				config.callback = callback;
				config.signal = signal;
				listeners.push(config);
			}
		}
		
		public function unmapSignal(signal:ISignal, callback:Function):void 
		{
			if (callback == null)
			{
				return;
			}
			if (signal)
			{
				signal.remove(callback);
				for (var i:int = listeners.length - 1; i >= 0 ; i--) 
				{
					var config:SignalMapConfig = listeners[i];
					if (config.callback == callback && config.signal == signal)
					{
						listeners.splice(i, 1);
						return;
					}
				}
			}
		}
		
		public function unmapSignals():void 
		{
			var len:int = listeners.length;
			for (var i:int = 0; i < len; i++) 
			{
				var config:SignalMapConfig = listeners[i];
				if (config.signal)
				{
					config.signal.remove(config.callback);
				}
			}
			listeners = [];
		}
		
	}

}
import org.osflash.signals.ISignal;

class SignalMapConfig
{
	public var callback:Function;
	public var signal:ISignal;
}